home *** CD-ROM | disk | FTP | other *** search
/ Oh!X 2000 Spring / Oh!X 2000 Spring Special CD-ROM (Japan) (Part 2).7z / Oh!X 2000 Spring Special CD-ROM (Japan) (Part 2).bin / DXF / samples / multimedia / dplay / src / duel / duel.cpp < prev    next >
C/C++ Source or Header  |  1999-07-27  |  18KB  |  538 lines

  1. //-----------------------------------------------------------------------------
  2. // File: Duel.cpp
  3. //
  4. // Desc: Multi-player game
  5. //
  6. // Copyright (C) 1995-1999 Microsoft Corporation. All Rights Reserved.
  7. //-----------------------------------------------------------------------------
  8. #define INITGUID
  9. #include "duel.h"
  10. #include "gameproc.h"
  11. #include "gfx.h"
  12. #include "DPUtil.h"
  13. #include "diutil.h"
  14. #include "dsutil.h"
  15. #include "lobby.h"
  16.  
  17.  
  18.  
  19. //-----------------------------------------------------------------------------
  20. // Globals
  21. //-----------------------------------------------------------------------------
  22. // This GUID allows DirectPlay to find other instances of the same game on
  23. // the network.  So it must be unique for every game, and the same for 
  24. // every instance of that game.  // {33925241-05F8-11d0-8063-00A0C90AE891}
  25. GUID g_AppGUID = { 0x33925241, 0x5f8, 0x11d0, { 0x80, 0x63, 0x0, 0xa0, 0xc9, 0xa, 0xe8, 0x91 } };
  26.  
  27. extern DWORD          g_dwFrameCount;
  28. extern DWORD          g_dwFrameTime;
  29. extern int            g_nProgramState;
  30. extern SHIP           g_OurShip;
  31. extern DPID           g_LocalPlayerDPID;
  32.  
  33. static BOOL           g_bReinitialize; // Used for switching display modes
  34.  
  35. TCHAR     g_strAppName[256] = "Duel";               // The name of the sample
  36. HANDLE    g_hDPMessageEvent = NULL;                 // Not used in this sample, needed for DPConnect.cpp
  37. TCHAR     g_strLocalPlayerName[MAX_PLAYER_NAME];    // Local player name
  38. TCHAR     g_strSessionName[MAX_SESSION_NAME];       // Default session name
  39. TCHAR     g_strPreferredProvider[MAX_SESSION_NAME]; // Default preferred provider
  40.  
  41. LPDPLCONNECTION    g_pDPLConnection = NULL;  
  42. LPDIRECTPLAYLOBBY3 g_pDPLobby       = NULL;  
  43.  
  44. HWND      g_hwndMain;             // Main application window handle
  45. HKEY      g_hDuelKey = NULL;      // Duel registry key handle
  46. HINSTANCE g_hInst;                // Application instance handle        
  47. BOOL      g_bShowFrameCount=TRUE; // Show FPS ?
  48. BOOL      g_bIsActive;            // Is the application active ?
  49. BOOL      g_bHostPlayer;          // Are we hosting or joining a game       
  50. DWORD     g_dwKeys;               // User keyboard input
  51. DWORD     g_dwOldKeys;            // Last frame's keyboard input
  52. BOOL      g_bFullscreen=FALSE;    // Window or FullScreen mode ?
  53. RECT      g_rcWindow;             // client rectangle of main window
  54. BOOL      g_bReliable;            // sends are reliable
  55. BOOL      g_bAsync;               // asynchronous sends
  56. BOOL      g_bAsyncSupported;      // asynchronous sends supported
  57. BOOL      g_bUseProtocol;         // DirectPlay Protocol messaging
  58.  
  59.  
  60.  
  61.  
  62. //-----------------------------------------------------------------------------
  63. // Function prototypes
  64. //-----------------------------------------------------------------------------
  65. extern int     DPConnect_StartDirectPlayConnect( HINSTANCE hInst, BOOL bBackTrack = FALSE );
  66. extern HRESULT DPConnect_CheckForLobbyLaunch( BOOL* pbLaunchedByLobby );
  67.  
  68. LONG WINAPI MainWndproc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
  69. HRESULT InitApplication( HINSTANCE hInst );
  70. HRESULT ReadRegKey( HKEY hKey, TCHAR* strName, TCHAR* strValue, DWORD dwLength, TCHAR* strDefault );
  71. HRESULT WriteRegKey( HKEY hKey, TCHAR* strName, TCHAR* strValue );
  72. VOID    CleanupApplication();
  73. BOOL    WasLaunchedByLobby();
  74. BOOL    FinishLobbyLaunch();
  75. VOID    DoHelp();
  76.  
  77.  
  78.  
  79.  
  80. //-----------------------------------------------------------------------------
  81. // Name: WinMain()
  82. // Desc:
  83. //-----------------------------------------------------------------------------
  84. int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int )
  85. {
  86.     MSG     msg;
  87.     BOOL    bLaunchedByLobby;
  88.     HRESULT hr;
  89.  
  90.     g_hInst = hInstance;
  91.  
  92.     // Read information from registry
  93.     RegCreateKeyEx( HKEY_CURRENT_USER, DUEL_KEY, 0, NULL,
  94.                     REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, 
  95.                     &g_hDuelKey, NULL );
  96.  
  97.     ReadRegKey( g_hDuelKey, "Player Name", 
  98.                 g_strLocalPlayerName, MAX_PLAYER_NAME, "" );
  99.     ReadRegKey( g_hDuelKey, "Session Name", 
  100.                 g_strSessionName, MAX_SESSION_NAME, "" );
  101.     ReadRegKey( g_hDuelKey, "Preferred Provider", 
  102.                 g_strPreferredProvider, MAX_SESSION_NAME, "" );
  103.  
  104.     CoInitialize( NULL );
  105.  
  106.     if( FAILED( InitApplication( hInstance ) ) )
  107.         return 0;
  108.  
  109.     // See if we were launched from a lobby server
  110.     hr = DPConnect_CheckForLobbyLaunch( &bLaunchedByLobby );
  111.     if( FAILED(hr) )
  112.         return 1;
  113.  
  114.     if( bLaunchedByLobby )
  115.     {
  116.         // Start game
  117.         PostMessage( g_hwndMain, UM_LAUNCH, 0, 0 );
  118.         g_bIsActive = TRUE;
  119.     }
  120.  
  121.     g_dwFrameTime = timeGetTime();
  122.  
  123.     while( TRUE )
  124.     {
  125.         if( g_bIsActive )
  126.         {
  127.             // Any windows messages ? (returns immediately)
  128.             if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
  129.             {
  130.                 if( !GetMessage( &msg, NULL, 0, 0 ) )
  131.                     break;
  132.  
  133.                 TranslateMessage( &msg );
  134.                 DispatchMessage( &msg );
  135.             }
  136.             else
  137.             {
  138.                 // Poll our receive queue. Polling is used in the sample only for simplicity.
  139.                 // Receiving messages using an event is the recommended way.
  140.                 if( g_nProgramState != PS_SPLASH )
  141.                 {
  142.                     ReceiveMessages();
  143.                     LobbyMessageReceive(LMR_PROPERTIES);
  144.                 }
  145.  
  146.                 // update screen
  147.                 if( !UpdateFrame() )
  148.                     ExitGame();     // posts QUIT msg
  149.             }
  150.         }
  151.         else
  152.         {
  153.             // Any windows messages ? (blocks until a message arrives)
  154.             if( !GetMessage( &msg, NULL, 0, 0 ) )
  155.                 break;
  156.  
  157.             TranslateMessage( &msg );
  158.             DispatchMessage( &msg );
  159.         }
  160.     }
  161.  
  162.     CoUninitialize();
  163.  
  164.     // Write information to the registry
  165.     WriteRegKey( g_hDuelKey, "Player Name", g_strLocalPlayerName );
  166.     WriteRegKey( g_hDuelKey, "Session Name", g_strSessionName );
  167.     WriteRegKey( g_hDuelKey, "Preferred Provider", g_strPreferredProvider );
  168.  
  169.     return msg.wParam;
  170. }
  171.  
  172.  
  173.  
  174.  
  175. //-----------------------------------------------------------------------------
  176. // Name: MainWndproc()
  177. // Desc: Callback for all Windows messages
  178. //-----------------------------------------------------------------------------
  179. LONG WINAPI MainWndproc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
  180. {
  181.     PAINTSTRUCT ps;
  182.     HDC         hdc;
  183.  
  184.     switch( msg )
  185.     {
  186.         case WM_SIZE:
  187.         case WM_MOVE:
  188.             // Get the client rectangle
  189.             if( g_bFullscreen )
  190.             {
  191.                 SetRect( &g_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN),
  192.                          GetSystemMetrics(SM_CYSCREEN) );
  193.             }
  194.             else
  195.             {
  196.                 GetClientRect( hWnd, &g_rcWindow );
  197.                 ClientToScreen( hWnd, (POINT*)&g_rcWindow );
  198.                 ClientToScreen( hWnd, (POINT*)&g_rcWindow+1 );
  199.             }
  200.             break;
  201.  
  202.         case WM_ACTIVATE:
  203.             // Ignore this message during reinitializing graphics
  204.             if( g_bReinitialize )
  205.                 return 0;
  206.  
  207.             // When we are deactivated, although we don't update our screen, we
  208.             // still need to to empty our receive queue periodically as
  209.             // messages will pile up otherwise. Polling the receive queue
  210.             // continuously even when we are deactivated causes our app to
  211.             // consume all the CPU time. To avoid hogging the CPU, we block on
  212.             // GetMessage() WIN API and setup a timer to wake ourselves up at
  213.             // regular intervals to process our messages.
  214.  
  215.             if( LOWORD(wParam) == WA_INACTIVE )
  216.             {
  217.                 // Aeactivated
  218.                 g_bIsActive = FALSE;
  219.                 if( PS_ACTIVE == g_nProgramState )
  220.                     SetTimer( hWnd, RECEIVE_TIMER_ID, RECEIVE_TIMEOUT, NULL );
  221.             }
  222.             else
  223.             {
  224.                 // Activated
  225.                 g_bIsActive = TRUE;
  226.                 if( PS_ACTIVE == g_nProgramState )
  227.                     KillTimer( hWnd, RECEIVE_TIMER_ID );
  228.             }
  229.  
  230.             // set game palette, if activated in game mode
  231.             if( g_bIsActive && (g_nProgramState != PS_SPLASH) )
  232.                 SetGamePalette();
  233.  
  234.             DIUtil_ReacquireInputDevices();
  235.  
  236.             return 0;
  237.  
  238.         case WM_CREATE:
  239.             break;
  240.  
  241.         case WM_SYSKEYUP:
  242.             switch( wParam )
  243.             {
  244.                 // Handle ALT+ENTER (fullscreen/window mode)
  245.                 case VK_RETURN:
  246.                     // Mode switch is allowed only during the game
  247.                     if( g_nProgramState == PS_ACTIVE )
  248.                     {
  249.                         g_bReinitialize = TRUE;
  250.                         ReleaseLocalData();  //only sound buffers have to be rels'd anyway.
  251.                         CleanupGameSounds();
  252.                         DIUtil_CleanupInput();
  253.                         CleanupGraphics();
  254.                         DestroyWindow( g_hwndMain );
  255.                         g_bFullscreen = !g_bFullscreen;
  256.                         InitGraphics();
  257.                         DIUtil_InitInput( g_hwndMain );
  258.                         InitializeGameSounds();
  259.                         InitLocalSoundData();
  260.                         g_bReinitialize = FALSE;
  261.                     }
  262.                     break;
  263.             }
  264.             break;
  265.  
  266.         case WM_KEYDOWN:
  267.             switch( wParam )
  268.             {
  269.                 case 'a':
  270.                 case 'A':
  271.                     // Toggle Async sends on/off
  272.                     if( g_bAsyncSupported )
  273.                     {
  274.                         g_bAsync = !g_bAsync;
  275.                         UpdateTitle();      // caption bar status
  276.                     }
  277.                     break;
  278.  
  279.                 case 'r':
  280.                 case 'R':
  281.                     // Toggle reliable sends
  282.                     g_bReliable = !g_bReliable;
  283.                     UpdateTitle();
  284.                     break;
  285.  
  286.                 case VK_F1:
  287.                     // Display help
  288.                     DoHelp();
  289.                     break;
  290.  
  291.                 case VK_F5:
  292.                     // Toggle frame rate display
  293.                     g_bShowFrameCount = !g_bShowFrameCount;
  294.                     if( g_bShowFrameCount )
  295.                     {
  296.                         g_dwFrameCount = 0;
  297.                         g_dwFrameTime = timeGetTime();
  298.                     }
  299.                     break;
  300.  
  301.                 case VK_RETURN:
  302.                     // Launch game setup wizard
  303.                     if( (g_nProgramState == PS_SPLASH) && !g_bFullscreen )
  304.                     {
  305.                         int nExitCode;
  306.                         nExitCode = DPConnect_StartDirectPlayConnect( g_hInst, FALSE );
  307.  
  308.                         // Figure out what happened, and post a reflecting message
  309.                         if( nExitCode == EXITCODE_FORWARD )
  310.                             PostMessage(g_hwndMain, UM_LAUNCH, 0, 0);
  311.  
  312.                         if( nExitCode == EXITCODE_QUIT )
  313.                             PostMessage(g_hwndMain, UM_ABORT, 0, 0);
  314.  
  315.                         if( nExitCode == EXITCODE_LOBBYCONNECT )
  316.                             PostMessage( g_hwndMain, UM_LAUNCH, 0, 0 );
  317.  
  318.                         if( nExitCode == EXITCODE_ERROR )
  319.                         {
  320.                             MessageBox( g_hwndMain, TEXT("Mutliplayer connect failed. "
  321.                                         "The sample will now quit."),
  322.                                         TEXT("DirectPlay Sample"), MB_OK | MB_ICONERROR );
  323.                             PostMessage(g_hwndMain, UM_ABORT, 0, 0);
  324.                         }
  325.                     }
  326.                     break;
  327.  
  328.                 case VK_ESCAPE:
  329.                 case VK_F12:
  330.                     // Exit the game
  331.                     ExitGame();
  332.                     return 0;
  333.             }
  334.             break;
  335.  
  336.         case WM_ERASEBKGND:
  337.             return 1;
  338.  
  339.         case WM_PAINT:
  340.             hdc = BeginPaint( hWnd, &ps );
  341.             if( g_nProgramState == PS_SPLASH )
  342.             {
  343.                 // Display the splash screen
  344.                 BltSplashScreen( NULL );
  345.             }
  346.  
  347.             EndPaint( hWnd, &ps );
  348.             return 1;
  349.  
  350.         case UM_LAUNCH:
  351.         case UM_ABORT:
  352.             // if we were launched by the lobby and not (failed to finish a lobby launch)
  353.             // where wParam is bLobbyLaunched
  354.             if( msg == UM_LAUNCH )
  355.             {
  356.                 // Init lobby msg support for reporting score
  357.                 // Note that we don't release the lobby object
  358.                 LobbyMessageInit();
  359.  
  360.                 // Start the game in rest mode
  361.                 g_nProgramState = PS_REST;
  362.                 LaunchGame();
  363.                 return 1;
  364.             }
  365.             // Else aborting
  366.             ExitGame();
  367.             return 1;
  368.  
  369.         case WM_TIMER:
  370.             ReceiveMessages();
  371.             LobbyMessageReceive( LMR_PROPERTIES );
  372.             break;
  373.  
  374.         case WM_DESTROY:
  375.             // If g_bReinitialize is TRUE don't quit, we are just switching
  376.             // display modes
  377.             if( !g_bReinitialize )
  378.             {
  379.                 CleanupApplication();
  380.                 PostQuitMessage( 0 );
  381.             }
  382.             return 0;
  383.  
  384.         default:
  385.             break;
  386.     }
  387.  
  388.     return DefWindowProc( hWnd, msg, wParam, lParam );
  389. }
  390.  
  391.  
  392.  
  393. //-----------------------------------------------------------------------------
  394. // Name: InitApplication()
  395. // Desc: Do that initialization stuff...
  396. //-----------------------------------------------------------------------------
  397. HRESULT InitApplication( HINSTANCE hInst )
  398. {
  399.     WNDCLASS wndClass = { CS_DBLCLKS, MainWndproc, 0, 0, hInst,
  400.                           LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN)),
  401.                           LoadCursor(NULL, IDC_ARROW), 
  402.                           (HBRUSH)GetStockObject(BLACK_BRUSH),
  403.                           NULL, TEXT("DuelClass") };
  404.     RegisterClass( &wndClass );
  405.  
  406.     // Initialize all components
  407.     if( FAILED( InitGraphics() ) )
  408.         return E_FAIL;
  409.     
  410.     if( FAILED( DIUtil_InitInput( g_hwndMain ) ) )
  411.         return E_FAIL;
  412.  
  413.     if( FAILED( InitializeGameSounds() ) )
  414.     {
  415.         // Can play game without sound. Do not exit
  416.     }
  417.  
  418.     // Start in splash mode
  419.     g_nProgramState = PS_SPLASH;
  420.  
  421.     return S_OK;
  422. }
  423.  
  424.  
  425.  
  426.  
  427. //-----------------------------------------------------------------------------
  428. // Name: CleanupApplication()
  429. // Desc: Calls clean up on all components
  430. //-----------------------------------------------------------------------------
  431. VOID CleanupApplication()
  432. {
  433.     CleanupComm();
  434.     CleanupGameSounds();
  435.     CleanupGraphics();
  436.     DIUtil_CleanupInput();
  437.     DPLobbyRelease();               // in case we were doing lobby messages
  438. }
  439.  
  440.  
  441.  
  442.  
  443. //-----------------------------------------------------------------------------
  444. // Name: ShowError()
  445. // Desc: Displays error to the user
  446. //-----------------------------------------------------------------------------
  447. VOID ShowError( int iStrID )
  448. {
  449.     TCHAR strMsg[MAX_ERRORMSG];
  450.     LoadString( g_hInst, iStrID, strMsg, MAX_ERRORMSG );
  451.     MessageBox( g_hwndMain, strMsg, TEXT("Duel Message"), MB_OK );
  452. }
  453.  
  454.  
  455.  
  456.  
  457. //-----------------------------------------------------------------------------
  458. // Name: UpdateTitle()
  459. // Desc: Updates the window title based on application status
  460. //-----------------------------------------------------------------------------
  461. VOID UpdateTitle()
  462. {
  463.     // Build the window title
  464.     TCHAR strTitle[MAX_WINDOWTITLE] = TEXT("Duel");
  465.  
  466.     // State options in window title
  467.     if( g_bHostPlayer | g_bUseProtocol | g_bReliable | g_bAsync )
  468.     {   
  469.         strcat( strTitle, " - |" );
  470.         if( g_bHostPlayer )
  471.             _tcscat( strTitle, TEXT(" Host |") );
  472.         if( g_bUseProtocol )
  473.             _tcscat( strTitle, TEXT(" Protocol |") );
  474.         if( g_bReliable )
  475.             _tcscat( strTitle, TEXT(" Reliable |") );
  476.         if( g_bAsync )
  477.             _tcscat( strTitle, TEXT(" Async |") );
  478.     }
  479.  
  480.     // Change window title
  481.     SetWindowText( g_hwndMain, strTitle );
  482. }
  483.  
  484.  
  485.  
  486.  
  487. //-----------------------------------------------------------------------------
  488. // Name: DoHelp()
  489. // Desc: Display a Help summary in a message box.
  490. //-----------------------------------------------------------------------------
  491. VOID DoHelp()
  492. {
  493.     TCHAR strHelpMsg[MAX_HELPMSG];
  494.     LoadString( g_hInst, IDS_DUEL_HELP, strHelpMsg, MAX_HELPMSG );
  495.     MessageBox( g_hwndMain, strHelpMsg, TEXT("DUEL"), MB_OK );
  496. }
  497.  
  498.  
  499.  
  500.  
  501. //-----------------------------------------------------------------------------
  502. // Name: ReadRegKey()
  503. // Desc: Read a registry key 
  504. //-----------------------------------------------------------------------------
  505. HRESULT ReadRegKey( HKEY hKey, TCHAR* strName, TCHAR* strValue, 
  506.                     DWORD dwLength, TCHAR* strDefault )
  507. {
  508.     DWORD dwType;
  509.     LONG bResult;
  510.  
  511.     bResult = RegQueryValueEx( hKey, strName, 0, &dwType, 
  512.                              (LPBYTE) strValue, &dwLength );
  513.     if ( bResult != ERROR_SUCCESS )
  514.         strcpy( strValue, strDefault );
  515.  
  516.     return S_OK;
  517. }
  518.  
  519.  
  520.  
  521.  
  522. //-----------------------------------------------------------------------------
  523. // Name: WriteRegKey()
  524. // Desc: Writes a registry key 
  525. //-----------------------------------------------------------------------------
  526. HRESULT WriteRegKey( HKEY hKey, TCHAR* strName, TCHAR* strValue )
  527. {
  528.     LONG bResult;
  529.  
  530.     bResult = RegSetValueEx( hKey, strName, 0, REG_SZ, 
  531.                              (LPBYTE) strValue, strlen(strValue) + 1 );
  532.     if ( bResult != ERROR_SUCCESS )
  533.         return E_FAIL;
  534.  
  535.     return S_OK;
  536. }
  537.  
  538.